package com.zg.nacos.config;

import com.zg.common.core.exception.BusinessException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import static com.zg.common.core.exception.E.ERROR;
import static com.zg.common.core.exception.E.NO_AUTH;

@Configuration
@Slf4j
public class WebClientConfig {

    /**
     * 配置 Nacos WebClient
     *
     * @param server Nacos 服务器地址
     * @return 配置好的 WebClient
     */
    @Bean
    public WebClient webClient(@Value("${spring.cloud.nacos.server-addr}") String server) {
        String formattedServer = formatServerUrl(server);
        return buildWebClient(formattedServer);
    }

    /**
     * 配置 Grafana WebClient
     *
     * @param server Grafana 服务器地址
     * @return 配置好的 WebClient
     */
    @Bean
    public WebClient grafanaClient(@Value("${grafana.domain}") String server) {
        String formattedServer = formatServerUrl(server);
        return buildWebClient(formattedServer)
                .mutate()
                .defaultHeader(MediaType.APPLICATION_JSON_VALUE)
//                .defaultHeader("x-grafana-device-id", "f7d6ed5453ba91cf0e19de6161bfd1ee") // 添加 x-grafana-device-id 请求头
                .build();
    }

    /**
     * 构建 WebClient 实例
     *
     * @param baseUrl WebClient 的基础 URL
     * @return 配置好的 WebClient
     */
    private WebClient buildWebClient(String baseUrl) {
        return WebClient.builder()
                .baseUrl(baseUrl)
                .filter((request, next) -> next.exchange(request)
                        .flatMap(this::handleResponse))
                .build();
    }

    /**
     * 处理 WebClient 的响应
     *
     * @param response 客户端响应
     * @return 处理后的响应 Mono
     */
    private Mono<ClientResponse> handleResponse(ClientResponse response) {
        if (response.statusCode().equals(HttpStatus.FORBIDDEN)) {
            log.error("Received response with status code {}:", response.statusCode());
            return response.bodyToMono(String.class)
                    .flatMap(errorBody -> {
                        log.error("Received response body: {}", errorBody);
                        return Mono.error(new BusinessException(NO_AUTH));
                    });
        }
        if (!response.statusCode().is2xxSuccessful()) {
            log.error("Received response with status code {}", response.statusCode());
            return response.bodyToMono(String.class)
                    .flatMap(errorBody -> Mono.error(new RuntimeException(
                            "HTTP error " + response.statusCode() + ": " + errorBody)));
        }
        return Mono.just(response);
    }

    /**
     * 格式化服务器 URL
     *
     * @param domain 服务器域名
     * @return 格式化后的 URL
     */
    private String formatServerUrl(String domain) {
        if (domain == null || domain.trim().isEmpty()) {
            throw new IllegalArgumentException("Server domain cannot be empty");
        }

        // 处理可能的逗号分隔的多个域名，取第一个
        if (domain.indexOf(",") > 0) {
            domain = domain.split(",")[0].trim();
        }

        // 添加协议前缀（如果没有的话）
        if (!domain.startsWith("http://") && !domain.startsWith("https://")) {
            domain = "http://" + domain;
        }

        return domain;
    }

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOriginPattern("*"); // 允许所有域名进行跨域调用
        config.addAllowedHeader("*"); // 允许任何请求头
        config.addAllowedMethod("*"); // 允许任何方法（POST、GET等）
        config.setAllowCredentials(true); // 允许携带凭证（Cookie）

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        return new CorsFilter(source);
    }
}